import java.nio.ByteBuffer;

public class RspHandler {
	
	private ByteBuffer buffer = ByteBuffer.allocate(8192);
	private byte[] rsp = null;
	private SIPTalk sipTalk;
	private SIPTalkUI sipTalkUI;
	XMLParser xmlParser;
	ParserHandler parserHandler;
	
	public RspHandler(SIPTalk sipTalk, SIPTalkUI sipTalkUI) {
		this.sipTalk = sipTalk;
		this.sipTalkUI = sipTalkUI;
		parserHandler = new ParserHandler();
		xmlParser = new XMLParser(parserHandler);
	}
	
	public synchronized boolean handleResponse(byte[] rsp) {
		this.rsp = rsp;
		this.notify();
		return true;
	}
	
	public synchronized void waitForResponse() {
		while(this.rsp == null) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		int len = buffer.position();
		String str;
		if(len != 0) {
			byte[] data = new byte[len];
			buffer.get(data, 0, len);
			byte[] rspData = new byte[rsp.length + len];
			System.arraycopy(data, 0, rspData, 0, len);
			System.arraycopy(this.rsp, 0, rspData, len, rspData.length);
			str = new String(rspData);
		} else {
			byte[] rspData = new byte[rsp.length];
			System.arraycopy(this.rsp, 0, rspData, 0, rspData.length);
			str = new String(rspData);
		}
		String tokens[] = str.split("\r\n\r\n");
		if(tokens.length > 0) {
			if(tokens[0].contains("Content-Length")) {
				String temp[] = tokens[0].split(":");
				int xmlLen = Integer.parseInt(temp[1].trim());
				int strLen = tokens[1].length();
				if(strLen == xmlLen) {
					parseXML(tokens[1]);
				} else if(strLen > xmlLen) {
					parseXML(tokens[1].substring(0, xmlLen));
					buffer.clear();
					buffer.put(tokens[1].getBytes(), xmlLen, strLen - xmlLen);
					buffer.flip();
				} else {
					buffer.clear();
					buffer.put(tokens[1].getBytes(), 0, strLen);
					buffer.flip();
				}
			}
		}
	}
	
	public void parseXML(String xml) {
		System.out.println("XML - " + xml);
		xmlParser.parse(xml);
		if(parserHandler.status.equals("critical")) {
			if(!parserHandler.desc.equals("")) {
				sipTalkUI.errorMessage(true, parserHandler.desc, "Error");
			} else {
				sipTalkUI.errorMessage(true, getDescription(parserHandler.code), "Error");
			}
			sipTalkUI.loadPanel("login");
		} else if (parserHandler.status.equals("error")) {
			boolean displayError = true;
			if (parserHandler.code.equals("107") || parserHandler.code.equals("106")) {
				sipTalk.ringPlayer.closeLine();
				if (sipTalk.uaState == sipTalk.CALL_SETUP || sipTalk.uaState == sipTalk.CALL_IN_PROGRESS) {
					sipTalk.uaState = sipTalk.REGISTERED;
					sipTalkUI.loadPanel("dialer");
				} else {
					displayError = false;
				}
			} else if (parserHandler.code.equals("108")) {
				sipTalk.ringPlayer.closeLine();
				sipTalkUI.removeConfirmDialog();
			}
			if (displayError) {
				if(!parserHandler.desc.equals("")) {
					sipTalkUI.errorMessage(false, parserHandler.desc, "Error");
				} else {
					sipTalkUI.errorMessage(false, getDescription(parserHandler.code), "Error");
				}
			}
		} else if(parserHandler.status.equals("success") && parserHandler.code.equals("102")) {
			sipTalk.uaState = sipTalk.REGISTERED;
			sipTalkUI.loadPanel("dialer");
		} else if (parserHandler.status.equals("")) {
			if (parserHandler.type.equals("call")) {
				sipTalk.ringPlayer.playAudio(sipTalk.ringPlayer.RING);
				sipTalkUI.callConfirmDialog(parserHandler.from, parserHandler.media);
			} else if (parserHandler.type.equals("ringing")) {
				sipTalk.ringPlayer.playAudio(sipTalk.ringPlayer.DIAL);
			} else if (parserHandler.type.equals("accept")) {
				sipTalk.ringPlayer.closeLine();
				sipTalk.uaState = sipTalk.CALL_IN_PROGRESS;
			} else if (parserHandler.type.equals("cancel")) {
				sipTalk.ringPlayer.closeLine();
				sipTalkUI.removeConfirmDialog();
			} else if (parserHandler.type.equals("bye")) {
				sipTalk.uaState = sipTalk.REGISTERED;
				sipTalkUI.loadPanel("dialer");
			}
		} 
	}
	
	public String getDescription(String code) {
		if(code.equals("101")) {
			return "Registration in Progresss";
		} else if(code.equals("102")) {
			return "Registration Successful";
		} else if(code.equals("103")) {
			return "Registration Failed";
		} else if(code.equals("104")) {
			return "Registration Timeout";
		} else if(code.equals("400")) {
			return "Bad Request";
		} else if(code.equals("401")) {
			return "Authentication Failed";
		} else if(code.equals("500")) {
			return "Request Failed";
		} else if(code.equals("504")) {
			return "Connection Failed";
		} else {
			return "Error Occurred in the Server";
		}
	}
}